<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
	<title>r2wUI</title>
<!--
	<meta content="yes" name="apple-mobile-web-app-capable" />
	<meta name="apple-mobile-web-app-status-bar-style" content="black" />
-->
	<link rel=Stylesheet href="style.css" type="text/css" />
	<meta name="viewport" content="width=340px, initial-scale=1" />
	<script src="script.js"></script>
<script>
function Ajax (method, uri, body, fn) {
        var x = new XMLHttpRequest ();
        x.open (method, uri, false);
	x.setRequestHeader ('Accept', 'text/plain');
        x.onreadystatechange = function (y) {
		if (x.status == 200) {
			if (fn) fn (x.responseText);
		} else alert ("ajax "+x.status)
        }
        x.send (body);
}

function cmd(c, cb) {
	Ajax ('GET', "/cmd/"+c, '', function (x) {
		if (cb) cb (x);
		else {
			x = filter_asm (x);
			document.getElementById ('output').innerHTML = x;
		}
	});
}

function hi(reg) {
	css ('a.rcx', 'background-color', 'yellow');
}

function about() { cmd ("?V", function (version) { alert ("r2w v"+version); }); }

function panel_functions_load() {
	Ajax ('GET', "/cmd/afl", '', function (x) {
		var arr = x.split ("\n");
		x = ''
		for (var i in arr) {
			var line = arr[i].replace (/\s+/g,' ').split (' ');
			var addr = line[0];
			var name = line[3];
			if (!addr) continue;
			x += "<a onclick=\"cmd('pdr@"+addr+"')\">"+addr+"</a> "+name+"\n";
		}
		popup_show ("Functions", x);
		document.getElementById('output').innerHTML = x;
	});
}
var debug_mode = false;

function runcmd(x) {
	popup_hide ();
	cmd (x, function() { cmd (display)});
}

function setmode (x) {
	popup_hide();
	display = x;
	if (backward) display = "pd";
	switch (x) {
	case "pd": x = "b 128;"+x; break;
	case "px": x = "b 512;"+x; break;
	}
	if (debug_mode && x=='pd')
		x = ".dr*;dr=;"+x;
	display = x
	cmd (x);
	window.scrollTo (0,0);
}

function runprompt (t, c) {
	popup_hide ();
	var msg = prompt (t);
	if (msg) cmd ('"'+c+msg+'"', function (x) {cmd (display);});
}

function toggle(x) {
	popup_hide();
	display = "pd";
	cmd ("e "+x, function (y) {
		var b = y.indexOf ("true")!=-1?  "false": "true";
		cmd ("e "+x+"=" + b, function (z) { cmd ("pd"); });
	});
}

var nl = "<br />";
var nl2 = "<br /><br />";
function show_popup_about () {
	var txt =
	"<a href='/enyo/'>Try new UI</a> (<a href='/enyo/two'>two panels</a>)<br />"+
	"<table class='popup_content'><tr><td valign=top>"+
		"Display"+
		"<hr size=1/>"+
		"<a href=\"javascript:setmode('pd')\" />pd</a>"+
		"&nbsp;"+
		"<a href=\"javascript:setmode('pdf')\" />pdf</a>"+
		"&nbsp;"+
		"<a href=\"javascript:setmode('px')\" />px</a>"+
		"&nbsp;"+
		"<a href=\"javascript:setmode('pxw')\" />pxw</a>"+
		"&nbsp;"+
		"<a href=\"javascript:setmode('afi $$;pdf');\">afi</a>"+
		"<br /><br />"+
		"Listings"+
		"<hr size=1/>"+
		"<a href=\"javascript:setmode('i',1)\" />file info</a><br />"+
		"<a href=\"javascript:setmode('isq',1)\" />symbols</a><br />"+
		"<a href=\"javascript:setmode('iiq',1)\" />imports</a><br />"+
		"<a href=\"javascript:setmode('afl',1)\" />functions</a><br />"+
		"<a href=\"javascript:setmode('izq',1)\" />strings</a><br />"+
		"<br />"+
		"Flags"+
		"<hr size=1/>"+
		"<a href=\"javascript:setmode('fs',1)\" />flagspaces</a><br />"+
		"<a href=\"javascript:setmode('f',1)\" />flags</a><br />"+
		"<a href=\"javascript:runprompt('Flag','f ')\" />set flag</a><br />"+
		"<a href=\"javascript:runprompt('Flag','f-')\" />unset flag</a><br />"+
	"</td><td valign=top>"+
		"Places"+
		"<hr size=1/>"+
		"<a href=\"javascript:popup_hide();setmode('pd');seek('entry0')\" />entry0</a>&nbsp;"+
		"<a href=\"javascript:popup_hide();setmode('pd');seek('main')\" />main</a><br />"+
		"<br />"+
		"Toggles"+
		"<hr size=1/>"+
		"<a href=\"javascript:toggle('asm.offset')\" />asm.offset</a><br />"+
		"<a href=\"javascript:toggle('asm.lines')\" />asm.lines</a><br />"+
		"<a href=\"javascript:toggle('asm.pseudo')\" />asm.pseudo</a><br />"+
		"<a href=\"javascript:toggle('asm.bytes')\" />asm.bytes</a><br />"+
		"<a href=\"javascript:toggle('cfg.bigendian')\" />cfg.bigendian</a><br />"+
		"&nbsp;"+
		"<br />"+
		"Actions"+
		"<hr size=1/>"+
		"<a href=\"javascript:runprompt('Comment','CC ')\" />set comment</a><br />"+
		"<a href=\"javascript:runprompt('Rename function','afr ')\" />rename function</a><br />"+
		"<a href=\"javascript:runcmd('af')\" />analyze function</a><br />"+
		"<a href=\"javascript:runcmd('aa');\">full analyze</a><br />"+
		"<a href=\"javascript:runcmd('ap');\">analyze preludes</a><br />"+
		"<a href=\"/graph/\">function graph</a>"+nl2+
		"&nbsp;"+
	"</td></tr></table>"+
		"";
	popup_show ("", txt);
}

function handleKeyPress(e, form) {
	var key = e.keyCode || e.which;
	if (key==13) {
		input_activate ();
	}
}

var seekindex = 0;
var seekhistory = [];

function seek_undo() {
	seekindex--;
	seekhistory[seekhistory.length-1] = x;
}

function seek_redo() {
	seekindex++;
	if (seekindex>=seekhistory.length) {
		seekindex--;
		return;
	}
	seek (seekhistory[seekindex]);
}

function seek_do(x) {
	seekindex++;
	seekhistory[seekhistory.length] = x;
}
function seek(x,back) {
	seek_do (x)
	next_curoff = prev_curoff = x;
	if (display[0] != 'p')
		setmode('pd');
	cmd ("s "+x, function (x) {
		if (display[0]=='f') display="pd";
		cmd (display);
		window.scrollTo (0,0);
	});
}

var prev_curoff = 0;
var prev_lastoff = 0;
var next_curoff = 0;
var next_lastoff = 0;
var backward = false;
var display = "pd";

function less () {
	var oldoff = document.body.scrollHeight;
	backward = true;
	cmd ("b", function (block) {
		cmd ("s "+prev_curoff+"-"+block+";"+display, function (x) {
			x = filter_asm (x);
			var body = document.getElementById ('output').innerHTML;
			document.getElementById ('output').innerHTML = x + body;
			var newoff = document.body.scrollHeight;
			var d= newoff-oldoff;
			document.body.scrollTop =d;
		});
	});
}

function hasmore(x) {
	var a = document.getElementById ("more");
	var b = document.getElementById ("less");
	if (x) {
		a.style.visibility=b.style.visibility="visible";
	} else {
		a.style.visibility=b.style.visibility="hidden";
	}
}

function more () {
	backward = false;
	cmd ("?v $l @ "+next_lastoff, function (oplen) {
		if (display == "px") oplen = 16;
		cmd (display+" @ "+next_lastoff+"+"+oplen, function (x) {
			x = filter_asm (x);
			document.getElementById('output').innerHTML += x;
		});
	});
}

function filter_asm(x) {
	var curoff = backward? prev_curoff: next_curoff;;
	var lastoff = backward? prev_lastoff: next_lastoff;;
	var lines = x.split (/\n/g);
	cmd ("s", function (x) { curoff = x; });
	for (var i=lines.length-1;i>0;i--)  {
		var a = lines[i].match (/0x([a-fA-F0-9]*)/);
		if (a && a.length>0) {
			lastoff = a[0].replace (/:/g, "");
			break;
		}
	}
	if (display == "afl") {
		hasmore (false);
		var z = "";
		for (var i=0;i<lines.length;i++)  {
			var row = lines[i].replace (/\ +/g," ").split (/ /g);
			z += row[0]+ "  "+row[3]+"\n";
		}
		x = z;
	} else
	if (display[0] == 'f') {
		hasmore (false);
		if (display[1] == 's') {
			var z = "";
			for (var i=0; i<lines.length; i++)  {
				var row = lines[i].replace (/\ +/g," ").split (/ /g);
				var mark = row[1]=='*'? '*': ' ';
				var space = row[2]? row[2]: row[1];
				if (!space) continue;
				z += row[0]+ " "+mark+" <a href=\"javascript:runcmd('fs "+
					space+"')\">"+space+"</a>\n";
			}
			x = z;
		} else {
		}
	} else
	if (display[0] == "i") {
		hasmore (false);
		if (display[1]) {
			var z = "";
			for (var i=0;i<lines.length;i++)  {
				var elems = lines[i].split (/ /g);
				var name = "";
				var addr = "";
				for (var j=0;j<elems.length;j++)  {
					var kv = elems[j].split (/=/);
					if (kv[0] == "addr") addr = kv[1];
					if (kv[0] == "name") name = kv[1];
					if (kv[0] == "string") name = kv[1];
				}
				z += addr+ "  "+name+"\n";
			}
			x = z;
		}
	} else hasmore (true);

	function haveDisasm(x) {
		if (x[0]=='p' && x[1]=='d') return true;
		if (x.indexOf (";pd") != -1) return true;
		return false;
	}
	if (haveDisasm (display)) {
		x = x.replace (/function:/g,"<span style=color:red>function:</span>");
		x = x.replace (/;(\s+)/g, ";");
		x = x.replace (/;(.*)/g, "// <span style='color:yellow'>$1</span>");
		x = x.replace (/(bl|call)/g, "<b style='color:green'>call</b>");
		x = x.replace (/(jmp|bne|beq|jnz|jae|jge|jbe|jg|je|jl|jz|jb|ja|jne)/g, "<b style='color:green'>$1</b>");
		x = x.replace (/(dword|qword|word|byte|movzx|movsxd|cmovz|mov\ |lea\ )/g, "<b style='color:yellow'>$1</b>");
		x = x.replace (/(hlt|leave|retn|ret)/g, "<b style='color:red'>$1</b>");
		x = x.replace (/(add|sub|mul|div|shl|shr|and|not|xor|inc|dec|sar|sal)/g, "<b style='color:orange'>$1</b>");
		x = x.replace (/(push|pop)/g, "<b style='color:magenta'>$1</b>");
		x = x.replace (/(test|cmp)/g, "<b style='color:green'>$1</b>");
		x = x.replace (/nop/g, "<b style='color:blue'>nop</b>");
		x = x.replace (/(sym|fcn|imp|loc).(.*)/g, "<a href='javascript:seek(\"$1.$2\")'>$1.$2</a>");
	}
	x = x.replace (/0x([a-zA-Z0-9]*)/g, "<a href='javascript:seek(\"0x$1\")'>0x$1</a>");
// registers
	if (backward) {
		prev_curoff = curoff;
		prev_lastoff = lastoff;
	} else {
		next_curoff = curoff;
		next_lastoff = lastoff;
		if (!prev_curoff)
			prev_curoff = next_curoff;
	}
	return x;
}

function input_activate () {
	var txt = document.getElementById('input').value;
	//if (txt.length == 0) show_popup_commands (); else
	if (txt.length == 0) show_popup_about (); else
	Ajax ('GET', '/cmd/'+txt, '', function (x) {
		x = filter_asm (x);
		document.getElementById('output').innerHTML = x;
		document.getElementById('input').value = '';
		if (x=="") cmd (display);
	});
}

function css(selector, property, value) {
	for (var i=0; i<document.styleSheets.length; i++) {
		try {
			document.styleSheets[i].insertRule (
				selector+ ' {'+property+':'+value+'}',
				document.styleSheets[i].cssRules.length);
		} catch (err) {
			try {
				document.styleSheets[i].addRule(
					selector, property+':'+value);
			} catch(err) {}
		}
	}
}

/* probably unnecesary */
window.onorientationchange = function() {
	var header = document.getElementById ('header');
	var orientation = window.orientation;
	switch (orientation) {
	case 0:
		css ('.header', 'width', '220px');
		css ('input', 'width', '190px');
		css ('.console', 'width', '320px');
		document.body.setAttribute ("class","portrait");
		break;
	case -90:
	case 90:
		css ('.header', 'width', '480');
		css ('input', 'width', '360');
		css ('.console', 'width', '470');
		document.body.setAttribute("class","landscape");
		break;
	}
}

function popup_hide () {
	var p = document.getElementById ("popup");
	var b = document.getElementById ("popup_background");
	p.style.visibility="hidden";
	b.style.visibility="hidden";
}

function popup_show (title, body) {
	var p = document.getElementById ("popup");
	var t = document.getElementById ("popup_title");
	var c = document.getElementById ("popup_content");
	var b = document.getElementById ("popup_background");
	if (title)
		t.innerHTML = title;
	if (body) {
		var top = document.body.scrollTop+10;
		var left = document.body.scrollLeft+10;
		c.innerHTML = body;
		p.style.visibility =
		b.style.visibility = "visible";
		//c.style.top = top; /* XXX doesnt works */
		css ('.popup', 'top', top+"px"); //'220px');
		css ('.popup', 'left', left+"px"); //'220px');
	}
	b.height = 100;
}

function menubar_display() {
/*
	var m = document.getElementById('menubar');
	var w = window.innerWidth;
	if (w<800) {
		m.style.top = 26;
		m.style.left = 12;
	}
*/
}

function toggle_editor() {
	var x = document.getElementById('x');
	var e = document.getElementById('editor');
	var et = document.getElementById('editor_textarea');
	var em = document.getElementById('editor_menu');
	if (et.style.visibility == "hidden") {
		e.style.width = 300;
		et.style.visibility = em.style.visibility="visible";
		x.innerHTML = "&gt;";
	} else {
		et.style.visibility = em.style.visibility="hidden";
		e.style.visibility = em.style.visibility="hidden";
		x.innerHTML = "&lt;";
	}
}

function notepad_run() {
	var t = document.getElementById ('editor_textarea').value;
	cmd (t.replace (/\n/g, ';'), function (out) {
		document.getElementById ('editor_textarea').value = out;
	});
}

function notepad_assemble () {
	var t = document.getElementById ('editor_textarea').value;
	cmd ("\"pa "+t.replace (/\n/g, ';')+"\"", function (out) {
		document.getElementById ('editor_textarea').value = out;
	});
}

var console2_toggle_var = false;
function console2_toggle () {
	var m = document.getElementById('menubar');
	var c = document.getElementById('console');
	var c2 = document.getElementById('console2');
	var b2 = document.getElementById('console2_body');
	console2_toggle_var = !console2_toggle_var;
	if (console2_toggle_var) {
		b2.style.visibility="visible";
		m.style.visibility="visible";
		c.style.left = 400;
		c2.style.width = 400;
	} else {
		b2.style.visibility="hidden";
		m.style.visibility="hidden";
		c.style.left = 20;
		c2.style.width = 20;
	}
}

function notepad_disassemble () {
	var t = document.getElementById ('editor_textarea').value;
	cmd ("pi@b:"+t.replace (/\n/g, ''), function (out) {
		document.getElementById ('editor_textarea').value = out;
	});
}

function notepad_clear() {
	document.getElementById ('editor_textarea').value = '';
}

function init() {
	var input = document.getElementById ('input');
	input.addEventListener ("activate", function (x) {
		input_activate();
	}, false);
	cmd (display);
	menubar_display ();

	r2.config_get ("cfg.debug", function(x) {
		debug_mode = true;
	});
}

var r2 = {
	'analyze': function () { runcmd ('af'); },
	'entry': function () { runcmd ('s entry0'); },
	'step': function () { runcmd ('ds;.dr*'); },
	'continue': function () { runcmd ('dc;.dr*'); },
	'step_over': function () { runcmd ('dso;.dr*'); },
	'hexdump': function () { setmode ("px"); },
	'disasm': function () { setmode ('pd'); },
	'incode': function (x) { setmode ('pc'+x); },
	'main': function () { runcmd ('s main'); },
	'config_get': function (x,y) { cmd ('e '+x, y); },
	'config_set': function (x) { runcmd ('s entry0'); }
}
</script>
</head>
<body id="body" onload="init()">


<div class=popup_background id="popup_background" style="visibility:hidden"></div>

<div id="editor" class="editor" style="visibility:hidden">
<table style="background-color:black">
<tr><td>
<div id="editor_menu">
<a title="execute selected text" href="javascript:notepad_run()">run</a>
<a title="assemble selected text" href="javascript:notepad_assemble()">asm</a>
<a title="disassemble selected text" href="javascript:notepad_disassemble()">dis</a>
<a title="clear textarea" href="javascript:notepad_clear()">clr</a>
</div>
</td></tr></table>
<textarea id="editor_textarea" class="editor_textarea" style="visibility:hidden">
</textarea>
</div>
<div id="popup" style="visibility:hidden">
<table class=popup>
<tr>
	<td style="text-align:left; width:100%">
	<div class=popup_title id="popup_title"></div>
</td><td style="text-align:right">
	<input type="button" class="button" value="x" onclick="popup_hide()">
	</td>
</tr>
<tr>
	<td colspan=2 valign="top" style="light">
		<div class="popup_content" id="popup_content"> </div>
	</td>
</tr>
</table>
</div>
<div style="position:fixed; top:0px;left:0px;width:100%;height:28px;background-color:black;border:0px;color:black;z-index:0"> .  </div>

<div>
<a href="javascript:seek_undo()">&lt;</a>
<a href="javascript:seek_redo()">&gt;</a>
</div>
<div style="position:fixed; top:0px;left:0px;background-color:black;border:0px">
	<table class=header>
	<tr><td style="text-align:left;vertical-align:top">
		<a href="javascript:show_popup_about ()"><img border=0 src="rlogo2.png" /></a>
	</td><td align="right" style="width:100%">
		<input autocapitalize="off" style="width:100%" onkeypress="handleKeyPress(event)" id="input">
	</td></tr>
	</table>
</div>
<div id="console2" class="console2">
<table style="height:100%">
<tr><td valign="top">
	&nbsp;<a href="javascript:console2_toggle()">]</a>
<br />
	&nbsp;<a href="javascript:toggle_editor()">[</a>
</td><td width="100%" valign="top">
<div id="menubar" style="visibility:hidden;color:white;">
cmds:
<a href="javascript:r2.hexdump()">x</a>
<a href="javascript:r2.disasm()">pd</a>
<a href="javascript:r2.incode()">pc</a>
|
<a href="javascript:r2.entry()">entry</a>
<a href="javascript:r2.main()">main</a>
<a href="javascript:r2.analyze()">a</a>
|
<a href="javascript:r2.break()">db</a>
<a href="javascript:r2.step()">ds</a>
<a href="javascript:r2.step_over()">dso</a>
<a href="javascript:r2.continue()">dc</a>
</div>
	<textarea class="editor_textarea" id="console2_body" style="visibility:hidden">
...
	</textarea>
</td></tr>
</table>
</div>

<div onresize="menubar_display()" id="console" class="console" style="top:45px !important; position:absolute;z-index:-99">

<div id="less" class="scroller" onclick="less()"> &nbsp;&nbsp;^^^
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; ^^^
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; ^^^
 </div>
<p id="output"></p>
<div id="more" class="scroller" onclick="more()"> &nbsp;&nbsp;vvv
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; vvv
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; vvv
</div>
<br /> <br />
</div>
</body>
</html>
